package failover

import (
	"basic-go/syntax/webook/internal/service/sms"
	"context"
	"errors"
	"sync/atomic"
)

type TimeoutFailoverSMSService struct {
	sms []sms.Service

	idx       int32
	cnt       int32
	threshold int32
}

func NewTimeoutFailoverSMSService(sms []sms.Service, threshold int32) *TimeoutFailoverSMSService {
	return &TimeoutFailoverSMSService{
		sms:       sms,
		threshold: threshold,
	}
}

func (t *TimeoutFailoverSMSService) Send(ctx context.Context, tpl string, args []string, numbers ...string) error {
	idx := atomic.LoadInt32(&t.idx)
	cnt := atomic.LoadInt32(&t.cnt)

	// 判断超时次数是否超过阈值，
	// 超过阈值，就把下边 +1 ,
	// 超时次数重新计数
	if cnt > t.threshold {
		newIdx := (idx + 1) % int32(len(t.sms))
		if atomic.CompareAndSwapInt32(&t.idx, idx, newIdx) {
			atomic.StoreInt32(&t.cnt, 0)
		}
		idx = newIdx
	}
	svc := t.sms[idx]
	err := svc.Send(ctx, tpl, args, numbers...)
	switch err {
	case nil:
		atomic.AddInt32(&t.cnt, 0)
		return nil
	case context.DeadlineExceeded:
		atomic.AddInt32(&t.cnt, 1)
		return err
	default:
	}
	return errors.New("发送失败")
}
